<template>
    <pre v-html="preSetColor(data)" id="preDom"></pre>
</template>
   
<script setup lang="ts">
const data = defineModel()
const props = defineProps({
    // 文字颜色
    colors: {
        type: Object,
        default: () => ({}),
    },
    // 展示json的时候，步长
    step: {
        type: [Number, String],
        default: 4,
    },
})
// 颜色映射关系
const colorMap = {
    string: 'green',
    number: 'darkorange',
    boolean: 'blue',
    null: 'magenta',
    key: 'red',
}
// 添加样式标签
const addStyle = () => {
    const obj = {
        ...colorMap,
        ...props.colors,
    }
    // 如果有了 就不创建了
    if (document.querySelector('#pre-id')) return
    const style = document.createElement('style')
    style.id = 'pre-id'
    style.innerText = `
      .string{ color: ${obj['string']} };
      .number{ color: ${obj['number']} };
      .boolean{ color: ${obj['boolean']} };
      .null{ color: ${obj['null']} };
      .key{ color: ${obj['key']} };
    `
    document.head.appendChild(style)
}
addStyle()
// pre设置颜色
const preSetColor = (data: string) => {
    const syntaxHighlight = (json: string) => {
        if (typeof json != 'string') {
            json = JSON.stringify(json, undefined, 2)
        }
        json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
        return json.replace(
            /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
            function (match) {
                var cls = 'number'
                if (/^"/.test(match)) {
                    if (/:$/.test(match)) {
                        cls = 'key'
                    } else {
                        cls = 'string'
                    }
                } else if (/true|false/.test(match)) {
                    cls = 'boolean'
                } else if (/null/.test(match)) {
                    cls = 'null'
                }
                return '<span class="' + cls + '">' + match + '</span>'
            },
        )
    }
    if(data === null || data === "" || data === undefined) return ''
    try {
        JSON.parse(data);
    } catch (e) {
        return data;
    }
    const handler = JSON.stringify(JSON.parse(data), null, +props.step)
    return syntaxHighlight(handler)
    
}
</script>

<style scoped>
pre {
    background: transparent !important;
    height: 100%;
    white-space: pre-wrap;
    word-wrap: break-word;
}
</style>